﻿using System;
using System.Web;
using System.Web.Caching;

namespace GONES.Cache
{
    /// <summary>
    /// 默认缓存管理类
    /// </summary>
    public class DefaultCacheStrategy : ICacheStrategy
    {
        private static readonly DefaultCacheStrategy instance = new DefaultCacheStrategy();

        protected static volatile System.Web.Caching.Cache webCache = HttpRuntime.Cache;

        /// <summary>
        /// 默认缓存存活期为3600秒(1小时)
        /// </summary>
        protected int _timeOut = 3600;


        public static System.Web.Caching.Cache GetWebCacheObj
        {
            get { return webCache; }
        }

        #region ICacheStrategy Members

        /// <summary>
        /// 设置到期相对时间[单位: 秒] 
        /// </summary>
        public virtual int TimeOut
        {
            set { _timeOut = value > 0 ? value : 3600; }
            get { return _timeOut > 0 ? _timeOut : 3600; }
        }

        /// <summary>
        /// 加入当前对象到缓存中
        /// </summary>
        /// <param name="objId">对象的键值</param>
        /// <param name="o">缓存的对象</param>
        public virtual void AddObject(string objId, object o)
        {
            AddObject(objId, o, false);
        }

        /// <summary>
        /// 加入当前对象到缓存中
        /// </summary>
        /// <param name="objId">对象的键值</param>
        /// <param name="o">缓存的对象</param>
        /// <param name="forever">是否永久缓存</param>
        public virtual void AddObject(string objId, object o, bool forever)
        {
            if (string.IsNullOrEmpty(objId) || o == null)
            {
                return;
            }

            CacheItemRemovedCallback callBack = OnRemove;

            if (forever)
            {
                webCache.Insert(objId, o, null, DateTime.MaxValue, TimeSpan.Zero,
                                CacheItemPriority.High, callBack);
            }
            else
            {
                webCache.Insert(objId, o, null, DateTime.Now.AddSeconds(TimeOut),
                                System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.High,
                                callBack);
            }
        }

        /// <summary>
        /// 加入当前对象到缓存中,并对相关文件建立依赖
        /// </summary>
        /// <param name="objId">对象的键值</param>
        /// <param name="o">缓存的对象</param>
        /// <param name="files">监视的路径文件</param>
        public virtual void AddObjectWithFileChange(string objId, object o, string[] files)
        {
            if (string.IsNullOrEmpty(objId) || o == null)
            {
                return;
            }

            CacheItemRemovedCallback callBack = OnRemove;

            var dep = new CacheDependency(files, DateTime.Now);

            webCache.Insert(objId, o, dep, DateTime.Now.AddSeconds(TimeOut),
                            System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.High,
                            callBack);
        }


        /// <summary>
        /// 加入当前对象到缓存中,并使用依赖键
        /// </summary>
        /// <param name="objId">对象的键值</param>
        /// <param name="o">缓存的对象</param>
        /// <param name="dependKey">依赖关联的键值</param>
        public virtual void AddObjectWithDepend(string objId, object o, string[] dependKey)
        {
            if (string.IsNullOrEmpty(objId) || o == null)
            {
                return;
            }

            CacheItemRemovedCallback callBack = OnRemove;

            var dep = new CacheDependency(null, dependKey, DateTime.Now);

            webCache.Insert(objId, o, dep, DateTime.Now.AddSeconds(TimeOut),
                            System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.High,
                            callBack);
        }

        /// <summary>
        /// 删除缓存对象
        /// </summary>
        /// <param name="objId">对象的关键字</param>
        public virtual void RemoveObject(string objId)
        {
            if (string.IsNullOrEmpty(objId))
            {
                return;
            }
            webCache.Remove(objId);
        }


        /// <summary>
        /// 返回一个指定的对象
        /// </summary>
        /// <param name="objId">对象的关键字</param>
        /// <returns>对象</returns>
        public virtual object RetrieveObject(string objId)
        {
            if (string.IsNullOrEmpty(objId))
            {
                return null;
            }
            return webCache.Get(objId);
        }

        #endregion

        /// <summary>
        /// 加入当前对象到缓存中
        /// </summary>
        /// <param name="objId">对象的键值</param>
        /// <param name="o">缓存的对象</param>
        public virtual void AddObjectWith(string objId, object o)
        {
            if (string.IsNullOrEmpty(objId) || o == null)
            {
                return;
            }

            CacheItemRemovedCallback callBack = OnRemove;

            webCache.Insert(objId, o, null, DateTime.Now.AddSeconds(TimeOut),
                            System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.High,
                            callBack);
        }

        /// <summary>
        /// 建立回调委托的一个实例
        /// </summary>
        /// <param name="key"></param>
        /// <param name="val"></param>
        /// <param name="reason"></param>
        public void OnRemove(string key, object val, CacheItemRemovedReason reason)
        {
            switch (reason)
            {
                case CacheItemRemovedReason.DependencyChanged:
                    break;
                case CacheItemRemovedReason.Expired:
                    break;
                case CacheItemRemovedReason.Removed:
                    break;
                case CacheItemRemovedReason.Underused:
                    break;
                default:
                    break;
            }
        }
    }
}